package org.sanguine.tests.protei.springapp.mvc.dao;

import org.sanguine.tests.protei.springapp.mvc.models.Entity;
import org.springframework.stereotype.Repository;
import org.springframework.util.SerializationUtils;

import java.util.*;
import java.util.logging.Logger;

/**
 * Created by alex on 03.03.14.
 * Author: Alex Kuznetsov
 */
@Repository
public class MockDatastore<T extends Entity> implements EntityDAO<T> {
    private final static Logger log = Logger.getLogger(MockDatastore.class.getName());

    private Integer keyCount = 0;
    private List<T> store = new ArrayList<T>();
    private Class<?> entityClass;

    private Integer keyFromString(String key) {
        Integer i;
        if (key == null || key.isEmpty()) return -1;
        try {
            i = new Integer(key);
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return -1;
        }
        return i-1;
    }

    @Override
    public T findByKey(String key) {
        Integer i = keyFromString(key);
        if (i >= 0 && i < keyCount) {
            T obj = (T)SerializationUtils.deserialize(SerializationUtils.serialize(store.get(i)));
            log.info("Found entity for key " + key + ". " + obj);
            return obj;
        }
        else return null;
    }

    @Override
    public boolean findAll(int page, int length, List<T> list) {
        Integer from = page*length;
        Integer to = (from + length) < keyCount ? (from + length) : keyCount;
        list.clear();
        int i = 0;
        int c = 0;
        while (c < from) {
            if (store.get(i++) != null) c++;
        }
        while (c < to) {
            T obj = findByKey("" + i);
            i++;
            if (obj != null) {
                c++;
                list.add(obj);
            }
        }
        log.info("Found entities, size list " + list.size());
        log.info("Last id is " + keyCount);

        return i < keyCount;
    }

    @Override
    public T addEntity(T newEntity) {
        if (newEntity != null) {
            Integer id = keyCount+1;
            newEntity.setId(id.toString());
            store.add(keyCount, (T)SerializationUtils.deserialize(SerializationUtils.serialize(newEntity)));
            keyCount++;
        }
        log.info("Added entity: " + newEntity);
        return newEntity;
    }

    @Override
    public boolean removeEntity(String key) {
        Integer i = keyFromString(key);
        if (i >= 0 && i < keyCount) {
            store.add(i, null);
            log.info("Removed entity for key " + key);
            return true;
        }
        return false;
    }

    @Override
    public boolean updateEntity(T entity) {
        if (entity != null) {
            Integer i = keyFromString(entity.getId());
            if (i >= 0 && i < keyCount) {
                store.add(i, (T)SerializationUtils.deserialize(SerializationUtils.serialize(entity)));
                log.info("Entity for key " + entity.getId() + " updated." + entity);
                return true;
            }
        }
        return false;
    }

    @Override
    public void setEntityType(Class<T> entityClass) {
        this.entityClass = entityClass;
    }
}
